home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 1999 #2 / Amiga Plus CD - 1999 - No. 2.iso / System-Boost / Workbench / Reboot / Reboot.c < prev    next >
C/C++ Source or Header  |  1998-06-17  |  29KB  |  1,049 lines

  1.  
  2. /*
  3. **
  4. **  $VER: Reboot.c 1.10 (4.6.1998)
  5. **  Reboot 1.10
  6. **
  7. **  main file
  8. **
  9. **  (C) Copyright 1994-1998 by Roland 'Gizzy' Mainz
  10. **          All Rights Reserved
  11. **
  12. */
  13.  
  14. /* We did not want any names before V36 */
  15. #define INTUI_V36_NAMES_ONLY 1
  16.  
  17. /* amiga includes */
  18. #include <exec/types.h>
  19. #include <utility/utility.h>
  20. #include <dos/dos.h>
  21. #include <intuition/intuition.h>
  22. #include <workbench/startup.h>
  23. #include <workbench/icon.h>
  24. #include <libraries/locale.h>
  25.  
  26. /* amiga prototypes */
  27. #include <clib/exec_protos.h>
  28. #include <clib/utility_protos.h>
  29. #include <clib/dos_protos.h>
  30. #include <clib/intuition_protos.h>
  31. #include <clib/icon_protos.h>
  32. #include <clib/locale_protos.h>
  33.  
  34. /* amiga pragmas */
  35. #include <pragmas/exec_pragmas.h>
  36. #include <pragmas/utility_pragmas.h>
  37. #include <pragmas/dos_pragmas.h>
  38. #include <pragmas/intuition_pragmas.h>
  39. #include <pragmas/icon_pragmas.h>
  40. #include <pragmas/locale_pragmas.h>
  41. #include <pragmas/alib_pragmas.h> /* tagcall stubs */
  42.  
  43. /* ansi includes */
  44. #include <string.h>
  45.  
  46. /* version string */
  47. #include "Reboot_rev.h"
  48.  
  49. /* locale */
  50. #define CATCOMP_NUMBERS
  51. #define CATCOMP_STRINGS
  52. #include "Reboot_strings.h"
  53.  
  54. /* misc defines */
  55. #ifndef NAME
  56. #define NAME "Reboot"
  57. #endif /* !NAME */
  58.  
  59. /* prototypes */
  60. #ifdef _DCC
  61.                 void                  chkabort( void );
  62.                 long                  wbmain( struct WBStartup * );
  63. #endif /* _DCC */
  64.  
  65.                 long                  main( long, STRPTR * );
  66.         static  void                  DefaultSettings( void );
  67.         static  void                  FreeInitProjectResult( void );
  68.         static  void                  ReadENVPrefs( void );
  69.  
  70.         static  void                  ClearRDA( void );
  71.         static  void                  ScanRDA( void );
  72.         static  void                  ScanToolTypes( STRPTR * );
  73.  
  74.         static  void                  RunTool( void );
  75.         static  BOOL                  OpenLibStuff( void );
  76.         static  void                  CloseLibStuff( void );
  77.         static  BOOL                  CreateBasicResources( void );
  78.         static  void                  DeleteBasicResources( void );
  79.                 void                  AttemptOpenLibrary( struct Library **, STRPTR, STRPTR, ULONG );
  80.         static  void                  RunTool( void );
  81.         static  void                  MyReboot( void );
  82.         static  STRPTR                SafeGetCatalogStr( struct Catalog *, LONG, STRPTR );
  83.         static  STRPTR                SafeGetLocaleStr( struct Locale *, LONG, STRPTR );
  84.  
  85.         static  struct DiskObject    *GetToolDiskObject( STRPTR );
  86.  
  87.  
  88.  
  89. /* version_string */
  90. STRPTR versionstring = VERSTAG;
  91.  
  92. long main_retval,
  93.      main_retval2;
  94.  
  95. static struct RDArgs  *startuprda;
  96.  
  97. /* shared libraries */
  98. extern struct Library *SysBase,
  99.                       *DOSBase;
  100.  
  101. struct Library *UtilityBase,
  102.                *IntuitionBase,
  103.                *IconBase,
  104.                *LocaleBase;
  105.  
  106. /* locale support */
  107. struct Locale  *loc;
  108. struct Catalog *ct;
  109.  
  110. /* templates for ReadArgs */
  111. #define STARTUP_TEMPLATE "REBOOTDELAY/K/N,QUIET=NOREQ/S,OFF/S,NOGUI/S"
  112. #define ENV_TEMPLATE     STARTUP_TEMPLATE /* no /A switches */
  113.  
  114.  
  115. static
  116. struct
  117. {
  118.     long *rebootdelay;
  119.     long *noreq;
  120.     long *off;
  121.     long *nogui;
  122. } result;
  123.  
  124. static
  125. struct
  126. {
  127.     ULONG rebootdelay;
  128.     BOOL  noreq;
  129.     BOOL  off;
  130.     BOOL  nogui;
  131. } project;
  132.  
  133.  
  134. #ifdef _DCC
  135. /* disable CTRL_C break support (DICE CTRL_C abort function) */
  136. void chkabort( void )
  137. {
  138. }
  139. #endif /* _DCC */
  140.  
  141.  
  142. /****** Reboot/Reboot ********************************************************
  143. *
  144. *    NAME
  145. *       Reboot -- rebooting utility
  146. *
  147. *    FORMAT
  148. *       Reboot [REBOOTDELAY <seconds>] [QUIET|NOREQ] [OFF] [NOGUI]
  149. *
  150. *    TEMPLATE
  151. *       REBOOTDELAY/K/N,QUIET=NOREQ/S,OFF/S,NOGUI/S
  152. *
  153. *    TOOLTYPES
  154. *       REBOOTDELAY/N
  155. *       QUIET/S
  156. *       NOREQ/S
  157. *       OFF/S
  158. *       NOGUI/S
  159. *
  160. *    PURPOSE
  161. *       To reboot the computer.
  162. *
  163. *    INTRODUCTION
  164. *       A simple tool to be used with Kickstart 2.x/3.x, written by
  165. *       Roland 'Gizzy' Mainz, freeware, all rights reserved.
  166. *       No guarantee of any kind is made that  the programm described below
  167. *       in this document is 100% reliable. You use this material on your own
  168. *       risk.
  169. *
  170. *       While playing with ENVOY 1.6, I need a program which allows to reboot
  171. *       another AMIGA through the network (by my own "RemoteNetShell") or
  172. *       after a given time.
  173. *       First I wrote a little script (using WAIT) and a C program calling
  174. *       exec.library/ColdReboot() to solve this problem.
  175. *       Switching to IAM's ENVOY 2.0 I replaced this script by this tool,
  176. *       adding some features (WB (including multiselect), SHELL ReadArgs,
  177. *       locale support and test mode).
  178. *
  179. *    DESCRIPTION
  180. *       Reboot is used to reboot the whole computer like a "cold"
  181. *       system start.
  182. *
  183. *       Unless you specify otherwise (through REBOOTDELAY option), reboot
  184. *       will wait 2 seconds before rebooting the system.
  185. *       This is used to let the system (and it's disk drives) settle.
  186. *       This delay time can't be less than 1 second, a REBOOTDELAY=0
  187. *       will also wait this minimum time.
  188. *
  189. *       Whenever the QUIET (or NOREQ) switch is set, the verify requesters
  190. *       ("Are you sure#?" etc.) will be suppressed.
  191. *
  192. *       If the OFF switch is set, the tool act like when a CTRL-C signal
  193. *       has been send to the tool.
  194. *
  195. *       Variable support:
  196. *         The environment REBOOT variable (either LOCAL or GLOBAL) can be
  197. *         used for default settings. The parsing template for this
  198. *         variable is the same like the shell template (see above).
  199. *
  200. *       Reboot supports workbench multiselect (e.g. project icons) !
  201. *
  202. *       The NOGUI option disables the requester and makes a simple
  203. *       console query. Currently, the NOGUI option should not be used
  204. *       if launched from WB.
  205. *
  206. *       If requesters have been disabled in a shell (using tools like DICE's
  207. *       "noreq" tool), the NOGUI option is on per default.
  208. *
  209. *    BUGS
  210. *       - Shell variables longer than 255 are currently not supported.
  211. *
  212. *       - Any errors during tooltype processing are ignored.
  213. *
  214. *       - The usage of the NOGUI option is not recommned to be used from
  215. *         WB.
  216. *
  217. *       - Does not work properly with my Apollo 2030 accerlator board.
  218. *         The system reboots, then hangs. Cause known,
  219. *         comments welcome.
  220. *
  221. *    NOTES
  222. *       "Set Reboot OFF" (e.g. use of a local variable) is only valid if
  223. *       you start Reboot from this shell.
  224. *
  225. *    HISTORY
  226. *       V1.1:
  227. *         - First release
  228. *
  229. *       V1.2:
  230. *         - The "Abort reboot" requester couldn't be canceld 1 second before
  231. *           the given time.
  232. *           Fixed.
  233. *
  234. *         - I did not read the autodocs exactly:
  235. *           The function BuildEasyRequest might return 0 or 1 at low mem time.
  236. *           Now Reboot simply fails with ERROR_NO_FREE_STORE for both 0 or 1.
  237. *           If 1 was returned, an enforcer hit would occur.
  238. *           Never happed, but
  239. *           fixed.
  240. *
  241. *         - AttemptOpenLibrary could return (sometimes) random pointers.
  242. *           In fact, this never happened by me, but maybe ...
  243. *           Fixed.
  244. *
  245. *         - While getting Reboot's environment variable, the "Abort reboot"
  246. *           requester might be canceled. Now we check this:
  247. *           Fixed.
  248. *
  249. *         - Additional, there was some code cleanup which adds support for
  250. *           DICE INLINE calls.
  251. *
  252. *         - The executable is now PURE and can be made resident.
  253. *
  254. *         - The time between the program checks the "Abort reboot" requester
  255. *           has been decrased down to a half second.
  256. *
  257. *       V1.3
  258. *         - Starting with V1.3 environment variables are supported.
  259. *           Things set in var "REBOOT" (local or global) will be parsed after
  260. *           built-in default settings and before any user-given arguments
  261. *           (shell args or project icons), which can overide those ENV
  262. *           settings given there.
  263. *
  264. *           This feature may cause Enforcer hits (I think so, I've never seen
  265. *           one).
  266. *
  267. *       V1.4
  268. *         - Starting with V1.4, ENV parsing should be safe.
  269. *           For Bug reports, I've included a Reboot.ld, which includes the
  270. *           debugging info used by Enforcer/FindHit.
  271. *
  272. *         - Running CPU FASTROM causes sometimes problems: The system reboots,
  273. *           but then hang atfer a while... ???
  274. *
  275. *       V1.5
  276. *         - Now I fully support SAS/C for all my projects (SMakefile
  277. *           included). A matching DMakefile is on the way.
  278. *
  279. *       V1.6
  280. *         - Unused utility.library code has been removed
  281. *
  282. *       V1.7
  283. *         - Recompiled with SAS/C 6.57
  284. *
  285. *         - Minor code cleanup.
  286. *
  287. *         - Moved contents of the #?.guide to this autodoc
  288. *
  289. *       V1.8
  290. *         - Added français catalog file
  291. *           Thanks to Julien Wilk (wilkj@esiee.fr).
  292. *
  293. *         - Added NOGUI option, e.g. localized console prompt :-)
  294. *
  295. *       V1.9
  296. *         - Silly mistake: I forgot to update the version string in V1.8.
  297. *           (Now the version string shows correctly V1.9).
  298. *
  299. *         - Recompiled with SAS/C 6.58 to get rid of some mc68060 problems.
  300. *
  301. *         - Fixed the longstanding bug that project icons did only work if
  302. *           Reboot's full path was given in "Default Tool".
  303. *
  304. *       V1.10
  305. *         - Added Croatia (hrvatski) catalog file.
  306. *           Thanks to Sinisa Lolic (vegi@usa.net).
  307. *
  308. *         - If a (required) shared library  cannot be opened,
  309. *           "Reboot" returns now ERROR_INVALID_RESIDENT_LIBRARY instead
  310. *           of ERROR_OBJECT_NOT_FOUND.
  311. *
  312. *         - The NOGUI option is now on per default if requesters have been
  313. *           disabled in the current shell (e..g if (thisproc -> pr_WindowPtr)
  314. *           is -1L).
  315. *
  316. *         - Added "SmallReboot" project for those people who said that 
  317. *           "Reboot" is too big. 
  318. *           The small sister of "Reboot" is only ~124 bytes small and still
  319. *           includes a version string...
  320. *
  321. *
  322. *    INSTALLATION
  323. *       After unpacking this archieve:
  324. *
  325. *       Workbench:
  326. *         - Drop the 'Reboot' icon in your favorite drawer (like
  327. *            "SYS:Utilities/").
  328. *           See SHELL for copying the catalog files.
  329. *
  330. *       Shell:
  331. *         - Unpack this archieve at "SYS:Utilities/"
  332. *           and add the following statements at your "S:user-startup" startup
  333. *           file:
  334. *
  335. *           Assign Reboot: SYS:Utilities/Reboot
  336. *           path Reboot: ADD
  337. *         OR
  338. *         - Drop/Copy the 'Reboot' file in your favorite directory
  339. *           (like "Sys:Utilities").
  340. *           To copy the (german) catalog files, type
  341. *           Copy Catalogs/#? TO="LOCALE:Catalogs/" ALL QUIET CLONE
  342. *
  343. *       SAS:
  344. *         - Type 'smake install' in shell
  345. *
  346. *    SOURCE
  347. *       DICE users may use DMakefile (if included).
  348. *       GNU-C support will be done in one future version.
  349. *
  350. *       All:
  351. *       If you like to include a new language (like Français or Nederlands
  352. *       etc.), send me a filled "Reboot_blank.ct" file named "Reboot_#?.ct"
  353. *       (#? for your language). As an example, see "Reboot_deutsch.ct".
  354. *       Note that I can currently only process "Reboot_#?.ct" files whose
  355. *       language is supported by AmigaOS 3.1 (e.g. a AmigaDOS Locale language
  356. *       driver exists).
  357. *
  358. *       SAS/C:
  359. *       Use SMakefile to create the executable.
  360. *       Note that the français locale file cannot be build with SAS/C SMake
  361. *       because it does not support the 'ç' character.
  362. *
  363. *    AUTHOR's REQUEST
  364. *        By  releasing  this program I do  not  place any obligations on you,
  365. *        feel free to share this program with your  friends (and enemies).
  366. *
  367. *        If you want to blame me, report any bugs, or wants a new version
  368. *        send your letter to:
  369. *                        Roland Mainz
  370. *                        Hohenstaufenstraße 8
  371. *                        52388 Nörvenich
  372. *                        GERMANY
  373. *
  374. *        Phone: (+49)(0)2426/901568
  375. *        Fax:   (+49)(0)2426/901569
  376. *
  377. *        EMAIL is also available:
  378. *        GISBURN@w-specht.rhein-ruhr.de
  379. *
  380. *        If you want to send me attachments larger than 1MB (up to 5MB,
  381. *        more with my permission):
  382. *        Up to August 1998 I'm reachable using this email address, too:
  383. *        Reinhold.A.Mainz@KBV.DE
  384. *
  385. *        | Please put your name and address in your mails !
  386. *        | German mailers should add their phone numbers.
  387. *        | See BUGS section above when submitting bug reports.
  388. *
  389. *        Sorry, but I can only look once a week for mails.
  390. *        If you don't hear something from me within three weeks, please
  391. *        send your mail again (but watch about new releases) (problems with
  392. *        this email port are caused by reconfigurations, hackers, network
  393. *        problems etc.).
  394. *
  395. *        The  entire  "Reboot"  package may  be  noncommercially
  396. *        redistributed, provided  that  the package  is always  distributed
  397. *        in it's complete  form (including it's documentation).  A small copy
  398. *        fee for media costs is okay but any kind of commercial distribution
  399. *        is strictly forbidden! Comments  and  suggestions  how  to  improve
  400. *        this program  are generally appreciated!
  401. *
  402. *        Thanks to Matt Dillon for his DICE, and Olaf 'Olsen'
  403. *        Barthel for his help, ideas and some text clips from his
  404. *        documentations.
  405. *
  406. *    SEE ALSO
  407. *        exec.library/ColdReboot
  408. *
  409. ******************************************************************************
  410. *
  411. */
  412.  
  413.  
  414. /* DICE workbench entry */
  415. #ifdef _DCC
  416. long wbmain( struct WBStartup *wbstartup )
  417. {
  418.     /* Call main like SAS-C */
  419.     return( main( 0L, (STRPTR *)wbstartup ) );
  420. }
  421. #endif /* _DCC */
  422.  
  423.  
  424. /* main program entry */
  425. long main( long ac, STRPTR *av )
  426. {
  427.     LONG               numArgs,
  428.                        x;
  429.     struct WBStartup  *wbstartup;
  430.     struct WBArg      *wbarg;
  431.     struct DiskObject *tooldobj,
  432.                       *projectdobj;
  433.     BPTR               oldToolLock    = NULL,
  434.                        oldProjectLock = NULL;
  435.  
  436.     main_retval  = RETURN_OK;
  437.     main_retval2 = 0L;
  438.  
  439.     if( CreateBasicResources() )
  440.     {
  441.       DefaultSettings();
  442.  
  443.       /* check if something goes wrong (ENV error etc.) */
  444.       if( main_retval == RETURN_OK )
  445.       {
  446. /* Workbench */
  447.         if( ac == 0L )
  448.         {
  449.           wbstartup = (struct WBStartup *)av;
  450.  
  451.           numArgs = wbstartup -> sm_NumArgs;
  452.           wbarg   = wbstartup -> sm_ArgList;
  453.  
  454.           if( *(wbarg[ 0 ] . wa_Name) )
  455.           {
  456.             if( wbarg[ 0 ] . wa_Lock )
  457.             {
  458.               oldToolLock = CurrentDir( (wbarg[ 0 ] . wa_Lock) );
  459.             }
  460.  
  461.             if( tooldobj = GetToolDiskObject( (wbarg[ 0 ] . wa_Name) ) )
  462.             {
  463.               /* two possible cases when started from workbench ... */
  464.               if( numArgs < 2L )
  465.               {
  466.                 /* ... first case, only our tool icon is given, create one project here */
  467.  
  468.                 ScanToolTypes( (STRPTR *)(tooldobj -> do_ToolTypes) );
  469.  
  470.                 /* check if something goes wrong (parsing error, etc.) */
  471.                 if( main_retval == RETURN_OK )
  472.                 {
  473.                   RunTool();
  474.                 }
  475.  
  476.                 FreeInitProjectResult();
  477.               }
  478.               else
  479.               {
  480.                 /* ... second case, a couple of project icons are given, multiple projects will start from here */
  481.                 for( x = 1L ; x < numArgs ; x++ )
  482.                 {
  483.                   if( wbarg[ x ] . wa_Lock )
  484.                   {
  485.                     oldProjectLock = CurrentDir( (wbarg[ x ] . wa_Lock) );
  486.                   }
  487.  
  488.                   if( *(wbarg[ x ] . wa_Name) )
  489.                   {
  490.                     if( projectdobj = GetDiskObject( (wbarg[ x ] . wa_Name) ) )
  491.                     {
  492.                       ScanToolTypes( (STRPTR *)(tooldobj -> do_ToolTypes) );
  493.                       ScanToolTypes( (STRPTR *)(projectdobj -> do_ToolTypes) );
  494.  
  495.                       /* check if something goes wrong (parsing error, etc.) */
  496.                       if( main_retval == RETURN_OK )
  497.                       {
  498.                         RunTool();
  499.                       }
  500.  
  501.                       FreeInitProjectResult();
  502.                       DefaultSettings();
  503.  
  504.                       FreeDiskObject( projectdobj );
  505.                     }
  506.                   }
  507.  
  508.                   if( wbarg[ x ] . wa_Lock )
  509.                   {
  510.                     CurrentDir( oldProjectLock );
  511.                   }
  512.                 }
  513.               }
  514.  
  515.               FreeDiskObject( tooldobj );
  516.             }
  517.  
  518.             if( wbarg[ 0 ] . wa_Lock )
  519.             {
  520.               CurrentDir( oldToolLock );
  521.             }
  522.           }
  523.         }
  524.         else
  525.         {
  526. /* CLI/Shell */
  527.           if( startuprda = ReadArgs( STARTUP_TEMPLATE, (LONG *)(&result), NULL ) )
  528.           {
  529.             /* did we get a CTRL_C signal ? */
  530.             if( !CheckSignal( SIGBREAKF_CTRL_C ) )
  531.             {
  532.               ScanRDA();
  533.  
  534.               /* check if something goes wrong (parsing error, etc.) */
  535.               if( main_retval == RETURN_OK )
  536.               {
  537.                 RunTool();
  538.               }
  539.  
  540.               FreeInitProjectResult();
  541.             }
  542.             else
  543.             {
  544.               /* SIGBREAKF_CTRL_C found */
  545.               main_retval  = RETURN_WARN;
  546.               main_retval2 = ERROR_BREAK;
  547.             }
  548.  
  549.             FreeArgs( startuprda );
  550.           }
  551.           else
  552.           {
  553.             /* ReadArgs failed */
  554.             main_retval  = RETURN_FAIL;
  555.             main_retval2 = IoErr();
  556.           }
  557.         }
  558.       }
  559.  
  560.       DeleteBasicResources();
  561.     }
  562.  
  563.     PrintFault( main_retval2, NAME );
  564.  
  565.     SetIoErr( main_retval2 );
  566.  
  567.     return( main_retval );
  568. }
  569.  
  570.  
  571. static
  572. void DefaultSettings( void )
  573. {
  574.     struct Process *ThisProcess = (struct Process *)FindTask( NULL );
  575.  
  576.     ClearRDA();
  577.     memset( (void *)(&project), 0, sizeof( project ) );
  578.  
  579.     /* Default values */
  580.     project . rebootdelay = 2UL;
  581.  
  582.     /* In the case that (ThisProcess -> pr_WindowPtr) is -1L the OS aborts requesters automatically.
  583.      * If we were launched from shell, we fore the NOGUI option that the user can be promped.
  584.      */
  585.     if( (ThisProcess -> pr_CLI) && ((ThisProcess -> pr_WindowPtr) == (APTR)-1L) )
  586.     {
  587.       project . nogui = TRUE;
  588.     }
  589.  
  590.     /* read prefs */
  591.     ReadENVPrefs();
  592. }
  593.  
  594.  
  595. static
  596. void ReadENVPrefs( void )
  597. {
  598.     struct RDArgs envvarrda =
  599.     {
  600.       NULL,
  601.       256L,
  602.       0L,
  603.       0L,
  604.       NULL,
  605.       0L,
  606.       NULL,
  607.       RDAF_NOPROMPT
  608.     };
  609.  
  610.     TEXT varbuff[ 258 ];
  611.  
  612.     envvarrda . RDA_Source . CS_Buffer = varbuff;
  613.  
  614.     if( GetVar( NAME, varbuff, 256L, 0UL ) != (-1L) )
  615.     {
  616.       strcat( varbuff, "\n" );
  617.  
  618.       if( ReadArgs( ENV_TEMPLATE, (LONG *)(&result), (&envvarrda) ) )
  619.       {
  620.         ScanRDA();
  621.  
  622.         FreeArgs( (&envvarrda) );
  623.       }
  624.       else
  625.       {
  626.         /* Can't parse ENV variable */
  627.         main_retval  = RETURN_FAIL;
  628.         main_retval2 = IoErr();
  629.       }
  630.     }
  631. }
  632.  
  633.  
  634. static
  635. void ClearRDA( void )
  636. {
  637.     memset( (void *)(&result), 0, sizeof( result ) );
  638. }
  639.  
  640.  
  641. static
  642. void ScanRDA( void )
  643. {
  644.     if( result . rebootdelay )
  645.     {
  646.       project . rebootdelay = (ULONG)(*(result . rebootdelay));
  647.     }
  648.  
  649.     if( result . noreq )
  650.     {
  651.       project . noreq = TRUE;
  652.     }
  653.  
  654.     if( result . off )
  655.     {
  656.       project . off = TRUE;
  657.     }
  658.  
  659.     if( result . nogui )
  660.     {
  661.       project . nogui = TRUE;
  662.     }
  663.  
  664.     ClearRDA();
  665. }
  666.  
  667.  
  668. static
  669. void ScanToolTypes( STRPTR *tt )
  670. {
  671.     STRPTR s;
  672.  
  673.     if( s = FindToolType( tt, "REBOOTDELAY" ) )
  674.       (void)StrToLong( s, (LONG *)(&(project . rebootdelay)) ); /* note: result ignored */
  675.  
  676.     if( s = FindToolType( tt, "NOREQ" ) )
  677.       result . noreq = (long *)s;
  678.  
  679.     if( s = FindToolType( tt, "QUIET" ) )
  680.       result . noreq = (long *)s;
  681.  
  682.     if( s = FindToolType( tt, "OFF" ) )
  683.       result . off = (long *)s;
  684.  
  685.     if( s = FindToolType( tt, "NOGUI" ) )
  686.       result . nogui = (long *)s;
  687.  
  688.     ScanRDA();
  689. }
  690.  
  691. static
  692. void FreeInitProjectResult( void )
  693. {
  694.     /* NOP */
  695. }
  696.  
  697.  
  698. static
  699. BOOL CreateBasicResources( void )
  700. {
  701.     return( OpenLibStuff() );
  702. }
  703.  
  704.  
  705. static
  706. void DeleteBasicResources( void )
  707. {
  708.     CloseLibStuff();
  709. }
  710.  
  711.  
  712. static
  713. BOOL OpenLibStuff( void )
  714. {
  715.     UtilityBase = IconBase = LocaleBase = NULL;
  716.  
  717.     if( IntuitionBase = OpenLibrary( "intuition.library", 37UL ) )
  718.     {
  719.       AttemptOpenLibrary( (&UtilityBase),  NAME, UTILITYNAME,      37UL );
  720.       AttemptOpenLibrary( (&IconBase),     NAME, ICONNAME,         37UL );
  721.       AttemptOpenLibrary( (&LocaleBase),   NAME, "locale.library", 38UL );
  722.  
  723.       if( LocaleBase )
  724.       {
  725.         loc = OpenLocale( NULL );
  726.         ct  = OpenCatalogA( NULL, (NAME ".catalog"), NULL );
  727.       }
  728.  
  729.       if( UtilityBase && IconBase )
  730.       {
  731.         return( TRUE );
  732.       }
  733.     }
  734.  
  735.     CloseLibStuff();
  736.  
  737.     /* Can't open requires libraries */
  738.     main_retval  = RETURN_FAIL;
  739.     main_retval2 = ERROR_INVALID_RESIDENT_LIBRARY;
  740.  
  741.     return( FALSE );
  742. }
  743.  
  744.  
  745. static
  746. void CloseLibStuff( void )
  747. {
  748.     if( LocaleBase )
  749.     {
  750.       CloseCatalog( ct );
  751.       CloseLocale( loc );
  752.  
  753.       CloseLibrary( LocaleBase );
  754.     }
  755.  
  756.     CloseLibrary( IconBase );
  757.     CloseLibrary( UtilityBase );
  758.     CloseLibrary( IntuitionBase );
  759. }
  760.  
  761.  
  762. void AttemptOpenLibrary( struct Library **library, STRPTR title, STRPTR libname, ULONG libversion )
  763. {
  764.     struct EasyStruct LibNotFoundES,
  765.                       LibWrongVersionES;
  766.  
  767.     LibNotFoundES . es_StructSize   = sizeof( struct EasyStruct );
  768.     LibNotFoundES . es_Flags        = 0UL;
  769.     LibNotFoundES . es_Title        = title;
  770.     LibNotFoundES . es_TextFormat   = SafeGetCatalogStr( ct, MSG_LIB_NOT_FOUND_REQTEXT, MSG_LIB_NOT_FOUND_REQTEXT_STR );
  771.     LibNotFoundES . es_GadgetFormat = SafeGetCatalogStr( ct, MSG_LIB_NOT_FOUND_REQGAD,  MSG_LIB_NOT_FOUND_REQGAD_STR );
  772.  
  773.     LibWrongVersionES . es_StructSize   = sizeof( struct EasyStruct );
  774.     LibWrongVersionES . es_Flags        = 0UL;
  775.     LibWrongVersionES . es_Title        = title;
  776.     LibWrongVersionES . es_TextFormat   = SafeGetCatalogStr( ct, MSG_LIB_WRONG_VERSION_REQTEXT, MSG_LIB_WRONG_VERSION_REQTEXT_STR );
  777.     LibWrongVersionES . es_GadgetFormat = SafeGetCatalogStr( ct, MSG_LIB_WRONG_VERSION_REQGAD,  MSG_LIB_WRONG_VERSION_REQGAD_STR );
  778.  
  779.     if( (*library) == NULL )
  780.     {
  781.       for( ;; )
  782.       {
  783.         /* attemp to open shared library */
  784.         (*library) = OpenLibrary( libname, 0UL );
  785.  
  786.         if( *library )
  787.         {
  788.           if( ((*library) -> lib_Version) < libversion )
  789.           {
  790.             EasyRequest( NULL, (&LibWrongVersionES), NULL, libname, libversion );
  791.  
  792.             CloseLibrary( (*library) );
  793.             (*library) = NULL;
  794.           }
  795.  
  796.           break;
  797.         }
  798.  
  799.         /* prompt the user */
  800.         if( EasyRequest( NULL, (&LibNotFoundES), NULL, libname ) == 0L )
  801.         {
  802.           /* user canceled */
  803.           break;
  804.         }
  805.       }
  806.     }
  807. }
  808.  
  809.  
  810. static
  811. void RunTool( void )
  812. {
  813.     if( project . noreq )
  814.     {
  815.       MyReboot();
  816.     }
  817.     else
  818.     {
  819.       if( project . nogui )
  820.       {
  821.         TEXT   buffer[ 8 ] = { 0 };
  822.         STRPTR yes = SafeGetLocaleStr( loc, YESSTR, "Yes" ),
  823.                no  = SafeGetLocaleStr( loc, NOSTR,  "No"  );
  824.  
  825.         Printf( "%s (%lc/%lc)\n", SafeGetCatalogStr( ct, MSG_REBOOT_REQTEXT, MSG_REBOOT_REQTEXT_STR ),
  826.                                   (ULONG)(*yes),
  827.                                   (ULONG)(*no) );
  828.  
  829.         Flush( Input()  ); /* Remove outstanding rubbish             */
  830.         Flush( Output() ); /* Be sure that the user got the message */
  831.  
  832.         FGets( Input(), buffer, (sizeof( buffer ) - 1UL) );
  833.  
  834.         /* Simple RETURN for yes or 'Y' (english) for ok) */
  835.         if( (*buffer == '\n') || (ToUpper( (ULONG)(*buffer) ) == ToUpper( (ULONG)(*yes) ) ) )
  836.         {
  837.           /* user wants to reboot */
  838.           MyReboot();
  839.         }
  840.         else
  841.         {
  842.           /* cancelled */
  843.           main_retval2 = ERROR_BREAK;
  844.           main_retval  = RETURN_WARN;
  845.         }
  846.       }
  847.       else
  848.       {
  849.         struct EasyStruct RebootES;
  850.  
  851.         RebootES . es_StructSize   = sizeof( struct EasyStruct );
  852.         RebootES . es_Flags        = 0UL;
  853.         RebootES . es_Title        = NAME;
  854.         RebootES . es_TextFormat   = SafeGetCatalogStr( ct, MSG_REBOOT_REQTEXT, MSG_REBOOT_REQTEXT_STR );
  855.         RebootES . es_GadgetFormat = SafeGetCatalogStr( ct, MSG_REBOOT_REQGAD,  MSG_REBOOT_REQGAD_STR );
  856.  
  857.         if( EasyRequestArgs( NULL, (&RebootES), NULL, NULL ) == 1L )
  858.         {
  859.           /* user wants to reboot */
  860.           MyReboot();
  861.         }
  862.         else
  863.         {
  864.           /* cancelled */
  865.           main_retval2 = ERROR_BREAK;
  866.           main_retval  = RETURN_WARN;
  867.         }
  868.       }
  869.     }
  870. }
  871.  
  872.  
  873. static
  874. void MyReboot( void )
  875. {
  876.     struct Window *abortreqwindow  = NULL;
  877.     ULONG          delay,
  878.                    x;
  879.     BOOL           abort           = FALSE;
  880.     ULONG          abortreqsignal,
  881.                    sigmask,
  882.                    signals;
  883.  
  884.     /* 1 second is the minimum reboot delay... */
  885.     if( (project . rebootdelay) < 1UL )
  886.     {
  887.       project . rebootdelay = 1UL;
  888.     }
  889.  
  890.     /* Prompt user ? */
  891.     if( !(project . noreq) )
  892.     {
  893.       if( project . nogui )
  894.       {
  895.         Printf( "%s\n", SafeGetCatalogStr( ct, MSG_ABORTREBOOT_REQTEXT, MSG_ABORTREBOOT_REQTEXT_STR ) );
  896.  
  897.         Flush( Input()  ); /* Remove outstanding rubbish            */
  898.         Flush( Output() ); /* Be sure that the user got the message */
  899.       }
  900.       else
  901.       {
  902.         struct EasyStruct AbortRebootES;
  903.  
  904.         AbortRebootES . es_StructSize   = sizeof( struct EasyStruct );
  905.         AbortRebootES . es_Flags        = 0UL;
  906.         AbortRebootES . es_Title        = NAME;
  907.         AbortRebootES . es_TextFormat   = SafeGetCatalogStr( ct, MSG_ABORTREBOOT_REQTEXT, MSG_ABORTREBOOT_REQTEXT_STR );
  908.         AbortRebootES . es_GadgetFormat = SafeGetCatalogStr( ct, MSG_ABORTREBOOT_REQGAD,  MSG_ABORTREBOOT_REQGAD_STR );
  909.  
  910.         /* Here we must check if we got the "low mem" return value (see BuildEasyRequestArgs autodoc)
  911.          * which may be 0 or 1
  912.          * For 0, I cannot determinate if this is a result from alert or a 'real' low mem failure
  913.          */
  914.         abortreqwindow = BuildEasyRequestArgs( NULL, (&AbortRebootES), 0UL, NULL );
  915.  
  916.         if( (abortreqwindow == ((struct Window *)1UL)) || (abortreqwindow == NULL) )
  917.         {
  918.           /* Can't open abort requester */
  919.           main_retval2 = ERROR_NO_FREE_STORE;
  920.           main_retval  = RETURN_FAIL;
  921.  
  922.           return;
  923.         }
  924.       }
  925.     }
  926.  
  927.     abortreqsignal = ((abortreqwindow)?(1UL << abortreqwindow -> UserPort -> mp_SigBit):(0UL));
  928.  
  929.     sigmask = SIGBREAKF_CTRL_C | abortreqsignal;
  930.  
  931. #define CHECKS_PER_SEC (2UL)
  932.     delay = (project . rebootdelay) * CHECKS_PER_SEC;
  933.  
  934.     /* for each cycle we'll check if any abort signal arrived (CTRL_C or requester) */
  935.     for( x = 0UL ; x <= delay ; x++ )
  936.     {
  937.       /* check if user aborts countdown */
  938.       signals = CheckSignal( sigmask );
  939.  
  940.       if( signals & SIGBREAKF_CTRL_C )
  941.       {
  942.         abort = TRUE;
  943.       }
  944.  
  945.       if( project . nogui )
  946.       {
  947.         /* Did user hit key for abort ? */
  948.         if( WaitForChar( Input(), 10L ) )
  949.         {
  950.           abort = TRUE;
  951.         }
  952.       }
  953.       else
  954.       {
  955.         /* no window, no signal, no event processing ... */
  956.         if( abortreqsignal )
  957.         {
  958.           if( signals & abortreqsignal )
  959.           {
  960.             if( SysReqHandler( abortreqwindow, NULL, FALSE ) == 0L )
  961.             {
  962.               abort = TRUE;
  963.             }
  964.           }
  965.         }
  966.       }
  967.  
  968.       if( abort )
  969.       {
  970.         break;
  971.       }
  972.  
  973.       /* wait a little bit */
  974.       Delay( (TICKS_PER_SECOND / CHECKS_PER_SEC) );
  975.     }
  976.  
  977.     /* No abort ? */
  978.     if( abort == FALSE )
  979.     {
  980.       if( abortreqwindow )
  981.       {
  982.         /* if we got no abort msg, check the requester for any outstanding msg */
  983.         if( SysReqHandler( abortreqwindow, NULL, FALSE ) == 0L )
  984.         {
  985.           abort = TRUE;
  986.         }
  987.       }
  988.     }
  989.  
  990.     /* Check if user send us CTRL-C or has selected test mode using something like "Setenv Reboot OFF" */
  991.     if( abort || (project . off) )
  992.     {
  993.       /* Aborted by requester or user-setup */
  994.       main_retval2 = ERROR_BREAK;
  995.       main_retval  = RETURN_WARN;
  996.     }
  997.     else
  998.     {
  999.       /* bite in the dust */
  1000.       ColdReboot();
  1001.     }
  1002.  
  1003.     /* user has aborted the rebooting sequence */
  1004.     FreeSysRequest( abortreqwindow );
  1005. }
  1006.  
  1007.  
  1008. static
  1009. STRPTR SafeGetCatalogStr( struct Catalog *ct, LONG id, STRPTR s )
  1010. {
  1011.     if( LocaleBase )
  1012.     {
  1013.       s = GetCatalogStr( ct, id, s );
  1014.     }
  1015.  
  1016.     return( s );
  1017. }
  1018.  
  1019.  
  1020. static
  1021. STRPTR SafeGetLocaleStr( struct Locale *loc, LONG id, STRPTR s )
  1022. {
  1023.     if( LocaleBase && loc )
  1024.     {
  1025.       s = GetLocaleStr( loc, id );
  1026.     }
  1027.  
  1028.     return( s );
  1029. }
  1030.  
  1031.  
  1032. static
  1033. struct DiskObject *GetToolDiskObject( STRPTR name )
  1034. {
  1035.     struct DiskObject *dobj;
  1036.     struct Process    *ThisProc = (struct Process *)FindTask( NULL );
  1037.     BPTR               olddir   = CurrentDir( (ThisProc -> pr_HomeDir) );
  1038.  
  1039.     dobj = GetDiskObjectNew( name );
  1040.  
  1041.     (void)CurrentDir( olddir );
  1042.  
  1043.     return( dobj );
  1044. }
  1045.  
  1046.  
  1047.  
  1048.  
  1049.